%
% Copyright 2016, Data61, CSIRO (ABN 41 687 119 230)
%
% SPDX-License-Identifier: BSD-2-Clause
%

This chapter explains the interfaces which make up the \refOS protocol. These interfaces set the language with which components in the system interact. Interfaces are intended to provide abstractions to manage conceptual objects such as a processes, files and devices.

Further implementations beyond \refOS may choose to extend these interfaces to provide extra system functionality and to attach additional interfaces.

% ----------------------------------------------------------------------
\section{Objects}

Servers implement interfaces which provide management (creation, destruction, monitoring, sharing and manipulation) of objects. For example, an audio device may implement the dataspace interface for UNIX \texttt{/dev/audio} which gives the abstraction to manage audio objects.

In \refOS, the access to an object (the permission to invoke the methods which manage the object) is implemented using a badged endpoint capability. The badge number is used to uniquely identify the instance of an object. Since most expected implementations of these protocols likely will use a similar method to track access permissions, the term capability may be used interchangably with object in this document. For example "window capability" means a capability which represents the access to a window object.

Note that in implementations, objects may be merged in some cases. For example, the process server's \obj{liveness}, \obj{anon} or \obj{process} object capabilities may be merged for simplification.

\begin{description}

	\item[\obj{process}] is an object which is most likely maintained by the process server (\srv{procserv}) and represents a process. If something has access to a process object, it may perform operations involving that process such as killing that process and calling methods on behalf of that process.
      
	\item[\obj{liveness}] is an object representing the identity of a process. If something has access to a liveness object of a process, it can be notified of the process's death and can request an ID to uniquely identify the process, but it cannot kill the process or pretend to be the process.
       
	\item[\obj{anon}] is an object representing the "address" of a server, and it is used to establish a session connection to the server.
    
	\item[\obj{session}] is an object representing an active connection session	to a server. If something has access to a session object, it can invoke methods on the server on behalf of the session client.
    
	\item[\obj{dataspace}] is an object that represents a dataspace. The dataspace itself may represent anything that may be modeled as a series of bytes including devices, RAM and files. If something has access to a dataspace object, it may read from the dataspace object, write to the dataspace object and execute the dataspace object by mapping a memory window to the dataspace, closing the dataspace, or deleting the dataspace. Performing these operations is dependent on the dataspace permissions.
      
	\item[\obj{memwindow}] is an object that represents an address space range (i.e. a memory window) segment in a process's virtual memory. If something has access to a memory window object, it may perform operations on the memory window object such as mapping the memory window to a dataspace and mapping a frame into the memory window.
    
\end{description}

% ----------------------------------------------------------------------
\section{Protocols}
\label{lProtocols}

This section describes a number of important protocols that \refOS employs. As noted in \autoref{mNotation} of this document, each protocol description consists of the server that is receiving and handling the method invocation via an endpoint, the name of the interface that the server implements, the name of the method call and the arguments that are passed to the method call and the return values, output variables and/or reply capabilities of the method invocation. Note that for simplification some method names differ slightly between this document and \refOS's implementation.

% ------------------
\subsection{Process Server Interface}

The process server interface provides the abstraction for managing processes and threads. The abstraction includes management of processes' virtual memory, memory window creation and deletion, process creation and deletion, death notification of client processes and thread management. Note that in implementations \cp{procserv}{session} could be the same capability as \cp{procserv}{process} in which case the process server is connectionless. \cp{procserv}{session} may also be shared with \cp{procserv}{anon} for simplification.

\begin{description}
	\item \pro{procserv}{session}{watch\_client(\cp{procserv}{liveness}, death\_notify\_ep)} 
	   {(Errorcode, death\_id, principle\_id)}   
    Authenticate a new client of a server against the \srv{procserv} and register for death
    notification.
    \begin{description}
        \item [procserv\_liveness\_C] The new client's liveness capability, which the client has given to the server through session connection
        \item [death\_notify\_ep] The asynchronous endpoint through which death notification occurs
        \item [death\_id] The unique client ID that the server will receive on death notification
        \item [principle\_id] The ID used for permission checking (optional)
    \end{description}

    \item \pro{procserv}{session}{unwatch\_client(\cp{procserv}{liveness})}{(Errorcode)}
    Stop watching a client and remove its death notifications.

	\item \pro{procserv}{session}{create\_mem\_window(base\_vaddr, size, permissions, flags)}
	   {(ErrorCode, \cp{procserv}{window})}
	Create a new memory window segment for the calling client. Note that clients may only create memory windows for their own address space and alignment restrictions may apply here due to implementation and/or hardware restrictions. In the \refOS client environment, a valid memory window segment must be covering any virtual address ranges before any mapping can be performed (including dataspace and device frame mappings).
    \begin{description}
        \item [base\_vaddr] The window base address in the calling client's VSpace
        \item [size] The size of the memory window
        \item [permissions] The read and write permission flags (optional)
        \item [flags] The extra flags bitmask - cached versus uncached window for example (optional)
    \end{description}

    \item \pro{procserv}{session}{resize\_mem\_window(\cp{procserv}{window}, size)}
        {ErrorCode}
    Resize a memory window segment. This is an optional feature, which may be useful for implementing dynamic heap memory allocation on clients.
    \begin{description}
        \item [size] The size of the memory window to resize to
    \end{description}

    \item \pro{procserv}{session}{delete\_mem\_window(\cp{procserv}{window})}
        {ErrorCode}
    Delete a memory window segment.

	\item \pro{procserv}{session}{register\_as\_pager(\cp{procserv}{window}, fault\_notify\_ep)} 
	   {(ErrorCode, window\_id)} 
    Register to receive faults for the presented window. The returned \ty{window\_id} is an integer used during notification in order for the pager to be able to identify which window faulted. \ty{window\_id} must be unique for each pager, although each \ty{window\_id} may also be implemented to be unique across the entire system.
    \begin{description}
        \item [fault\_notify\_ep] The asynchronous endpoint which fault notifications are to be sent through
        \item [window\_id] The unique ID of the window which is used to identify which window faulted. The server most likely has to record this ID to handle faults correctly
    \end{description}

    \item \pro{procserv}{session}{unregister\_as\_pager(\cp{procserv}{window})}{(ErrorCode)} 
    Unregister to stop being the pager for a client process's memory window

	\item \pro{procserv}{session}{window\_map(\cp{procserv}{window}, window\_offset, src\_addr)}
	   {ErrorCode}
	Map the frame at the given VSpace into a client's faulted window and then resolve the fault and resume execution of the faulting client. This protocol is most commonly used in response to a prior fault notification from the process server, and it also may be used to eagerly map frames into clients before they VMfault.
    \begin{description}
        \item [window\_offset] The offset into the window to map the frame into
        \item [src\_addr] The address of the source frame in the calling client process's VSpace. This address should contain a valid frame, and page-alignment restrictions may apply for this parameter
    \end{description}
	
	\item \pro{procserv}{session}{new\_proc(name, params, block, priority)}{(ErrorCode, status)}
	Start a new process, blocking or non-blocking.
    \begin{description}
        \item [name] The executable file name of the process to start
        \item [params] The parameters to pass onto the new process
        \item [block] The flag stating to block or not to block until the child process exits
        \item [priority] The priority of the new child process
        \item [status] The exit status of the process (only applicable if blocking)
    \end{description}

    \item \pro{procserv}{session}{exit(status)}{(ErrorCode)}
    Exit and delete the calling process
    \begin{description}
        \item [status] The exit status of the calling client process
    \end{description}

    \item \pro{procserv}{session}{clone(entry, stack, flags, args)}{(ErrorCode, thread\_id)}
    Start a new thread, sharing the current client process's address space. The child thread will have the same priority as the parent process.
    \begin{description}
        \item [entry] The entry point vaddr of the new thread
        \item [stack] The stack vaddr of the new thread
        \item [flags] Any thread-related flags
        \item [args] The thread arguments
        \item [thread\_id] The thread ID of the cloned thread
    \end{description}

\end{description}

% ------------------
\subsection{Server Connection Interface}

The server connection interface enables client session connection and disconnection. It may be a good idea during implementation to extend this interface onto any other extra operating system functionality that is common across servers. This could include debug ping, parameter buffer setup and notification buffer setup.

\begin{description}

    \item \pro{serv}{anon}{connect(\cp{procserv}{liveness})}{(ErrorCode, \cp{serv}{session})}
        Connect to a server and establish a session

    \item \pro{serv}{session}{disconnect()}{(ErrorCode)}
        Disconnect from a server and delete session

\end{description}

% ------------------
\subsection{Data Server Interface}

The data server interface provides the abstraction for management of dataspaces including dataspace creation, dataspace access, dataspace sharing and dataspace manipulation.

\begin{description}
      
    \item \pro{dataserv}{session}{open(char *name, flags, mode, size)}
        {(ErrorCode, \cp{dataserv}{dataspace})}
    Open a new dataspace at the dataspace server, which represents a series of bytes. Dataspace mapping methods such as datamap() and init\_data() directly or indirectly map the contents of a dataspace into a memory window after which the contents can be read from and written to. The concept of a dataspace in \refOS is similar to a file in UNIX: what a dataspace represents depends on the server that is implementing the interface.
    \begin{description}
        \item [name] The name of the dataspace to open
        \item [flags] The read, write and create flags to open the dataspace with
        \item [mode] The mode to create a new file with in the case that a new one is created
        \item [size] The size of dataspace to open - some data servers may ignore this
    \end{description}

    \item \pro{dataserv}{session}{close(\cp{dataserv}{dataspace})}{ErrorCode}
    Close a dataspace belonging to the data server.

    \item \pro{dataserv}{session}{expand(\cp{dataserv}{dataspace}, size)}{ErrorCode}
    Expand a given dataspace. Note that some dataspaces may not support this method as sometimes the size of a dataspace makes no sense (serial input for instance).
    \begin{description}
        \item [size] The size to expand the dataspace to
    \end{description}

    \item \pro{dataserv}{session}{datamap(\cp{dataserv}{dataspace}, \cp{procserv}{window}, offset)}
        {ErrorCode}
    Request that the data server back the specified window with the specified dataspace. Offset is the offset into the dataspace to be mapped to the start of the window. Note that the dataspace has to be provided by the session used to request the backing of the window.
    \begin{description}
        \item [procserv\_window\_C] Capability to the memory window to map the dataspace contents into
        \item [offset] The offset in bytes from the beginning of the dataspace
    \end{description}

    \item \pro{dataserv}{session}{dataunmap(\cp{procserv}{window})}
        {ErrorCode}
    Unmap the contents of the data from the given memory window.
    \begin{description}
        \item [procserv\_window\_C] Capability to the memory window to unmap the dataspace from
    \end{description}

    \item \pro{dataserv}{session}{init\_data(\cp{dest}{dataspace}, \cp{dataserv}{dataspace},
        offset)}{ErrorCode}
    Initialise a dataspace by the contents of a source dataspace. The source dataspace is where the content is, and the source dataspace must originate from the invoked dataserver. Whether the destination dataspace and the source dataspace can originate from the same dataserver depends on the dataserver implementation: one should refer to the dataserver documentation. One example use case for this is a memory manager implementing the dataspace for RAM having a block of RAM initialised by an external data source such as a file from a file server.
    \begin{description}
        \item [dest\_dataspace\_C] The dataspace to be initialised with content from the source dataspace
        \item [dataserv\_dataspace\_C] The dataserver's own dataspace (where the content is)
        \item [offset] The content offset into the source dataspace
    \end{description}

    \item \pro{dataserv}{session}{have\_data(\cp{dataserv}{dataspace}, fault\_ep)}
        {ErrorCode, data\_id}
    Call a remote dataspace server to have the remote dataspace server initalised by the contents of the local dataspace server. The local dataspace server must bookkeep the remote dataspace server's ID. The remote dataspace server then will request from the given endpoint content initialisation with the remote dataspace server providing its ID in the notification.
    \begin{description}
        \item [fault\_ep] The asynchronous endpoint to ask for content initialisation with
        \item [data\_id] The remote endpoint's unique ID number
    \end{description}

    \item \pro{dataserv}{session}{unhave\_data(\cp{dataserv}{dataspace})}
        {ErrorCode}
    Inform the dataserver to stop providing content initialise data for its dataspace.

    \item \pro{dataserv}{session}{provide\_data(\cp{dataserv}{dataspace}, offset, content\_size)}
        {ErrorCode}  
    Give the content from the local dataserver to the remote dataserver in response to the remote dataserver's earlier notification asking for content. The content is assumed to be in the set up parameter buffer. This call implicitly requires a parameter buffer to be set up, and how this is done is up to the implementation. Even though the notification from the dataserver asking for content uses an ID to identify the dataspace, the reply, for security reasons, gives the actual dataspace capability. The ID may be used securely if the dataserver implementation supports per-client ID checking, and in this situtation a version of this method with an ID instead of a capability could be added.
    \begin{description}
        \item [offset] The offset into the remote dataspace to provide content for
        \item [content\_size] The size of the content
    \end{description}

    \item \pro{dataserv}{process}{datashare(\cp{dataserv}{dataspace})}
        {ErrorCode}
    Share a dataspace of a dataserver with another process. The exact implementation of this is context-based. For example, a server sharing a parameter buffer may implement this method as \texttt{share\_param\_buffer(dataspace\_cap)}, implicitly stating the context and implementing multiple share calls for more contexts. Although this method of stating the sharing context is strongly encouraged, the exact method of passing context is left up to the implementation. \\
    There are also a few assumptions here:
    \begin{itemize}
    \item The dataspace is backed by somebody the receiving process trusts (the process server for instance)
    \item The dataspace is not revocable, so the receiving process does not need to protect itself from an untrusted fault handler on that memory
    \end{itemize}

    \item \pro{dataserv}{event}{pagefault\_notify(window\_id, offset, op)}
        {ErrorCode} 
    Send a notification event to a data server indicating which window a page fault occurred in, the offset within that window and the operation attempted (either read or write)

    \item \pro{dataserv}{event}{initdata\_notify(data\_id, offset)}
        {ErrorCode}
    Send a notification event to a data server indicating that a dataspace needs its initial data

    \item \pro{dataserv}{event}{death\_notify(death\_id)}
        {ErrorCode}
    Send a notification event to a data server indicating a client has died and that the resources associated with the client can be cleaned up
  
\end{description}

% ------------------
\subsection{Name Server Interface}

The name server interface provides a naming protocol. \refOS employs a simple hierachical distributed naming scheme where each server is responsible for a particular prefix under another name server. This allows for simple distributed naming while allowing prefix caching. In \refOS, the process server acts as the root name server.

\begin{description}

    \item \pro{nameserv}{session}{register(name, \cp{dataserv}{anon})}
        {ErrorCode}
    Create an endpoint and set this endpoint on the root name server in order for clients to be able to find the root name server and connect to it. The anon capability is given to clients looking for the root name server, and then clients make their connection calls through the anon capability to establish a session. Re-registering replaces the current server anon capability.
    \begin{description}
        \item [name] The name to register under
        \item [dataserv\_anon\_C] The anonymous endpoint to register with
    \end{description}

    \item \pro{nameserv}{session}{unregister(name)}
        {ErrorCode}
    Unregister a server under a given name so clients are no longer able to find the server under that name. This method invalidates existing anon capabilities.
    \begin{description}
        \item [name] The name to unregister for
    \end{description}

    \item\pro{nameserv}{session}{resolve\_segment(path)}
        {(ErrorCode, \cp{dataserv}{anon}, resolved\_bytes)}
    Return an anon capability if the server is found. This method resolves part of the path string returned as an offset into the path string that has been resolved. The rest of the path string may be resolved by other dataspaces until the system reaches the endpoint to the server that contains the file that it is searching for. This allows for a simple hierachical namespace with distributed naming.
    \begin{description}
        \item [path] The path to resolve
        \item [resolved\_bytes] The number of bytes resolved from the start of the path string
    \end{description}

\end{description}

% ----------------------------------------------------------------------
\section{Server Components}

\refOS follows the component-based multi-server operating system design. The two main components in the design are the process server and the file server. \refOS implements an additional operating system server which is a dataserver that is responsible for basic device related tasks.

% ------------------
\subsection{Process Server}

The process server is the most trusted component in the system. It runs as the initial kernel thread and does not depend on any other component (this avoids deadlock). The process server implementation is single-threaded. The process server also implements the dataspace interface for anonymous memory and acts as the memory manager.

In \refOS, the process server implements the following interfaces:
\begin{itemize}
    \item Process server interface (naming, memory windows, processes and so on)
    \item Dataspace server interface (for anonymous memory)
    \item Name server interface (in \refOS, the process server acts as the root name server)
\end{itemize}

% ------------------
\subsection{File Server}

The file server is more trusted than clients, but it is less trusted than the process server (this avoids deadlock). In \refOS, the file server does not use a disk driver and the actual file contents are compiled into the file server executable itself using a cpio archive. The file server acts as the main data server in \refOS.

In \refOS, the file server implements the following interfaces:
\begin{itemize}
    \item Dataspace server interface (for stored file data)
    \item Server connection interface (for clients to connect to it)
\end{itemize}

% ------------------
\subsection{Console Server}

The console server provides serial and EGA input and output functionality, which is exposed through the dataspace interface. The console server also provides terminal emulation for EGA screen output.

In \refOS, the console server implements the following interfaces:
\begin{itemize}
    \item Dataspace server interface (for serial input and output and EGA screen devices)
    \item Server connection interface (for clients to connect to it)
\end{itemize}

% ------------------
\subsection{Timer Server}

The timer server provides timer get time and sleep functionality, which is exposed through the dataspace interface.

In \refOS, the timer server implements the following interfaces:
\begin{itemize}
    \item Dataspace server interface (for timer devices)
    \item Server connection interface (for clients to connect to it)
\end{itemize}
